/**
 * 轻量级API工具
 * 统一响应格式，简化错误处理，保持TSRPC原有结构
 */

import { ApiCall, TsrpcErrorType } from 'tsrpc';

/**
 * 标准API响应格式
 */
export interface StandardApiResponse<T = any> {
    success: boolean;
    data?: T;
    error?: {
        code: string;
        message: string;
        details?: any;
    };
    timestamp: string;
}

/**
 * API错误类型
 */
export enum ApiErrorCode {
    // 参数错误
    INVALID_PARAMS = 'INVALID_PARAMS',
    MISSING_PARAMS = 'MISSING_PARAMS',
    
    // 权限错误
    UNAUTHORIZED = 'UNAUTHORIZED',
    FORBIDDEN = 'FORBIDDEN',
    
    // 业务错误
    PLAYER_NOT_FOUND = 'PLAYER_NOT_FOUND',
    PLAYER_OFFLINE = 'PLAYER_OFFLINE',
    INSUFFICIENT_RESOURCES = 'INSUFFICIENT_RESOURCES',
    
    // 系统错误
    INTERNAL_ERROR = 'INTERNAL_ERROR',
    SERVICE_UNAVAILABLE = 'SERVICE_UNAVAILABLE',
    NOT_IMPLEMENTED = 'NOT_IMPLEMENTED'
}

/**
 * API辅助工具类
 * 提供统一的成功/错误响应和参数验证
 */
export class ApiHelper {
    /**
     * 统一成功响应
     * 保持TSRPC的call.succ()方式，但提供标准格式
     */
    static success<TRes>(call: ApiCall<any, TRes>, data: TRes): void {
        call.succ(data);
    }

    /**
     * 带格式的成功响应
     * 可选的标准格式响应
     */
    static successWithFormat<T>(call: ApiCall<any, StandardApiResponse<T>>, data: T): void {
        call.succ({
            success: true,
            data,
            timestamp: new Date().toISOString()
        });
    }

    /**
     * 统一错误响应
     * 使用标准错误格式
     */
    static error(
        call: ApiCall<any, any>, 
        code: ApiErrorCode | string, 
        message: string, 
        details?: any
    ): void {
        call.error({
            message,
            code,
            type: TsrpcErrorType.ApiError,
            details,
            timestamp: new Date().toISOString()
        });
    }

    /**
     * 快速错误响应方法
     */
    static invalidParams(call: ApiCall<any, any>, message: string = '参数无效', details?: any): void {
        this.error(call, ApiErrorCode.INVALID_PARAMS, message, details);
    }

    static missingParams(call: ApiCall<any, any>, fields: string[]): void {
        this.error(call, ApiErrorCode.MISSING_PARAMS, `缺少必需参数: ${fields.join(', ')}`, { fields });
    }

    static playerNotFound(call: ApiCall<any, any>, playerId?: string): void {
        this.error(call, ApiErrorCode.PLAYER_NOT_FOUND, '玩家不存在', { playerId });
    }

    static playerOffline(call: ApiCall<any, any>, playerId?: string): void {
        this.error(call, ApiErrorCode.PLAYER_OFFLINE, '玩家未在线', { playerId });
    }

    static unauthorized(call: ApiCall<any, any>, message: string = '未授权访问'): void {
        this.error(call, ApiErrorCode.UNAUTHORIZED, message);
    }

    static notImplemented(call: ApiCall<any, any>, apiName?: string): void {
        this.error(call, ApiErrorCode.NOT_IMPLEMENTED, 'API未实现', { apiName });
    }

    static internalError(call: ApiCall<any, any>, message: string = '内部服务器错误', error?: Error): void {
        this.error(call, ApiErrorCode.INTERNAL_ERROR, message, { 
            stack: error?.stack,
            name: error?.name 
        });
    }

    /**
     * 参数验证工具
     */
    static validateRequired(params: any, requiredFields: string[]): { isValid: boolean; missing: string[] } {
        const missing = requiredFields.filter(field => {
            const value = params[field];
            return value === undefined || value === null || value === '';
        });
        
        return {
            isValid: missing.length === 0,
            missing
        };
    }

    /**
     * 带验证的API调用包装器
     * 自动处理参数验证和错误
     */
    static async withValidation<TReq, TRes>(
        call: ApiCall<TReq, TRes>,
        requiredFields: string[],
        handler: (call: ApiCall<TReq, TRes>) => Promise<void>
    ): Promise<void> {
        try {
            // 参数验证
            const validation = this.validateRequired(call.req, requiredFields);
            if (!validation.isValid) {
                this.missingParams(call, validation.missing);
                return;
            }

            // 执行处理器
            await handler(call);
        } catch (error) {
            console.error('API执行错误:', error);
            
            if (error instanceof Error) {
                // 已知错误类型，直接返回
                if (error.message.includes('玩家不存在')) {
                    this.playerNotFound(call);
                } else if (error.message.includes('未在线')) {
                    this.playerOffline(call);
                } else {
                    this.internalError(call, error.message, error);
                }
            } else {
                this.internalError(call, '未知错误');
            }
        }
    }

    /**
     * 玩家状态检查
     * 常用的玩家验证逻辑
     */
    static checkPlayerExists(player: any, call: ApiCall<any, any>, playerId?: string): boolean {
        if (!player) {
            this.playerNotFound(call, playerId);
            return false;
        }
        return true;
    }

    static checkPlayerOnline(player: any, call: ApiCall<any, any>, playerId?: string): boolean {
        if (!player) {
            this.playerOffline(call, playerId);
            return false;
        }
        return true;
    }

    /**
     * 类型安全的参数获取
     */
    static getParam<T>(call: ApiCall<any, any>, paramName: string, defaultValue?: T): T {
        return call.req[paramName] ?? defaultValue;
    }

    static getRequiredParam<T>(call: ApiCall<any, any>, paramName: string): T {
        const value = call.req[paramName];
        if (value === undefined || value === null) {
            throw new Error(`Missing required parameter: ${paramName}`);
        }
        return value;
    }

    /**
     * 数字参数验证
     */
    static validateNumber(value: any, paramName: string, min?: number, max?: number): number {
        const num = Number(value);
        if (isNaN(num)) {
            throw new Error(`参数 ${paramName} 必须是数字`);
        }
        if (min !== undefined && num < min) {
            throw new Error(`参数 ${paramName} 不能小于 ${min}`);
        }
        if (max !== undefined && num > max) {
            throw new Error(`参数 ${paramName} 不能大于 ${max}`);
        }
        return num;
    }

    /**
     * 字符串参数验证
     */
    static validateString(value: any, paramName: string, minLength?: number, maxLength?: number): string {
        if (typeof value !== 'string') {
            throw new Error(`参数 ${paramName} 必须是字符串`);
        }
        if (minLength !== undefined && value.length < minLength) {
            throw new Error(`参数 ${paramName} 长度不能少于 ${minLength} 个字符`);
        }
        if (maxLength !== undefined && value.length > maxLength) {
            throw new Error(`参数 ${paramName} 长度不能超过 ${maxLength} 个字符`);
        }
        return value;
    }

    /**
     * 枚举参数验证
     */
    static validateEnum<T extends Record<string, string | number>>(
        value: any, 
        enumObject: T, 
        paramName: string
    ): T[keyof T] {
        const validValues = Object.values(enumObject);
        if (!validValues.includes(value)) {
            throw new Error(`参数 ${paramName} 必须是以下值之一: ${validValues.join(', ')}`);
        }
        return value;
    }

    /**
     * 记录API调用日志
     */
    static logApiCall<TReq, TRes>(call: ApiCall<TReq, TRes>, apiName: string): void {
        const startTime = Date.now();
        console.log(`[API调用] ${apiName} - 开始`, {
            params: call.req,
            timestamp: new Date().toISOString()
        });

        // 在响应中记录结束时间
        const originalSucc = call.succ.bind(call);
        const originalError = call.error.bind(call);

        call.succ = (res: TRes) => {
            const duration = Date.now() - startTime;
            console.log(`[API成功] ${apiName} - 完成 (${duration}ms)`, { response: res });
            originalSucc(res);
        };

        call.error = (error: any) => {
            const duration = Date.now() - startTime;
            console.log(`[API错误] ${apiName} - 失败 (${duration}ms)`, { error });
            originalError(error);
        };
    }
}
